PRG 1.0 TXT

/*
	Triangle Tessellation Program
*/

//-----------------------------------------------------------------------------
// [CONFIG]

include "..\program_include.ocf"

object Program
{
	type		= e_program.DISPLACEMENT;
	layer_bits	= e_render_layer_bits.ALL;
	
	ubo_data	= array /*UBO*/ {
		{ "inMaterial", e_program_data.MATERIAL }
	}

	textures	= array /*ProgramTexture*/ {
		{ "unDiffuseMap", e_texture.DIFFUSE },
		{ "unNormalMap",  e_texture.NORMAL },
		{ "unHeightMap",  e_texture.HEIGHT }
	}
	
	uniforms	= array /*string*/ {
		"transform", "unTransform."
	}
}


//-----------------------------------------------------------------------------
// [VERTEX]

#version 410 core
#pragma optimize(on)

#define ATTR_POSITION		0
#define ATTR_NORMAL			1
#define ATTR_TEXCOORD_0		2

layout(location = ATTR_POSITION)	in vec3 inPosition;
//layout(location = ATTR_NORMAL)		in vec3 inNormal;
layout(location = ATTR_TEXCOORD_0)	in vec2 inTexcoord;

uniform sampler2D	unHeightMap;

uniform struct TTransform {
	mat4	MVP;
} unTransform;


layout(std140)
uniform inMaterial {
	vec3	vLightNormal;
	float	fHeightScale;
	float	fDetailLevel;
	float	fMaxLevel;
	float	fQuadSize;
} unParams;


out	TVertexData {
	vec4	vPos;
	vec2	vTexcoord;
	float	fLevel;
} Output;


bool InScreen(in vec2 in_pos, in float z)
{
	const float		size = 1.7;
	float			quad = unParams.fQuadSize;
	return ( abs(in_pos.x) <= size &&
			 abs(in_pos.y) <= size ) ||
		    ( z > -quad && z < quad );
}


float Level(in vec4 in_pos)
{
	if ( InScreen( in_pos.xy/in_pos.w, in_pos.z ) )
	{
		float	d = unParams.fDetailLevel / length( in_pos ) - 2.0;
		return clamp( d, 1.0, unParams.fMaxLevel );
	}
	else
		return 0.0;
}

void main()
{
	Output.vTexcoord	= inTexcoord;
	vec4	pos			= vec4(inPosition.yzx, 1.0);
	gl_Position  		= pos;
	pos.y			   += texture( unHeightMap, inTexcoord ).r * unParams.fHeightScale;
	pos					= unTransform.MVP * pos;
	Output.vPos			= pos;
	Output.fLevel		= Level( pos );
}


//-----------------------------------------------------------------------------
// [TESS_CONTROL]

#version 410 core
#pragma optimize(on)

#define I 	gl_InvocationID

layout(vertices = 3) out;

layout(std140)
uniform inMaterial {
	vec3	vLightNormal;
	float	fHeightScale;
	float	fDetailLevel;
	float	fMaxLevel;
	float	fQuadSize;
} unParams;


in	TVertexData {
	vec4	vPos;
	vec2	vTexcoord;
	float	fLevel;
} Input[];

out	TContData {
	vec2	vTexcoord;
} Output[3];


bool InScreen(in vec2 in_pos, in float z)
{
	const float		size = 1.7;
	float			quad = unParams.fQuadSize;
	return ( abs(in_pos.x) <= size &&
			 abs(in_pos.y) <= size ) ||
		    ( z > -quad && z < quad );
}


float Level(in vec4 in_pos)
{
	if ( InScreen( in_pos.xy/in_pos.w, in_pos.z ) )
	{
		float	d = unParams.fDetailLevel / length( in_pos ) - 2.0;
		return clamp( d, 1.0, unParams.fMaxLevel );
	}
	else
		return 0.0;
}


float Level()
{
	vec4	p = (Input[0].vPos + Input[1].vPos + Input[2].vPos) / vec4(3.0, 3.0, 3.0, 1.0);
	float	l = Level( p );
	return max( max( Input[0].fLevel, Input[1].fLevel ), max( Input[2].fLevel, l ) );
}


void main()
{
	if ( I == 0 )
	{
		float	f_level = Level();
		gl_TessLevelInner[0] = f_level;
		f_level = f_level > 0.0 ? 1.0 : 0.0;
		gl_TessLevelOuter[0] = max( max( Input[1].fLevel, Input[2].fLevel ), f_level );
		gl_TessLevelOuter[1] = max( max( Input[0].fLevel, Input[2].fLevel ), f_level );
		gl_TessLevelOuter[2] = max( max( Input[0].fLevel, Input[1].fLevel ), f_level );
	}
	
	gl_out[I].gl_Position	= gl_in[I].gl_Position;
	Output[I].vTexcoord		= Input[I].vTexcoord;
}


//-----------------------------------------------------------------------------
// [TESS_EVALUATION]

#version 410 core
#pragma optimize(on)

layout(triangles, equal_spacing, ccw) in;
//layout(triangles, fractional_even_spacing, ccw) in;
//layout(triangles, fractional_odd_spacing, ccw) in;

uniform sampler2D	unHeightMap;

uniform struct TTransform {
	mat4	MVP;
} unTransform;


layout(std140)
uniform inMaterial {
	vec3	vLightNormal;
	float	fHeightScale;
	float	fDetailLevel;
	float	fMaxLevel;
	float	fQuadSize;
} unParams;


in	TContData {
	vec2	vTexcoord;
} Input[];

out	TEvalData {
	vec2	vTexcoord;
} Output;


float PCF(in vec2 texcoord)
{
	/*
	float	res = 0.0;
	res += textureOffset( unHeightMap, texcoord, ivec2(-1,-1) ).r;
	res += textureOffset( unHeightMap, texcoord, ivec2(-1, 0) ).r;
	res += textureOffset( unHeightMap, texcoord, ivec2(-1, 1) ).r;
	res += textureOffset( unHeightMap, texcoord, ivec2( 0,-1) ).r;
	res += textureOffset( unHeightMap, texcoord, ivec2( 0, 0) ).r * 2.0;
	res += textureOffset( unHeightMap, texcoord, ivec2( 0, 1) ).r;
	res += textureOffset( unHeightMap, texcoord, ivec2( 1,-1) ).r;
	res += textureOffset( unHeightMap, texcoord, ivec2( 1, 0) ).r;
	res += textureOffset( unHeightMap, texcoord, ivec2( 1, 1) ).r;
	return ( res * 0.1 );
	/*/
	return texture( unHeightMap, texcoord ).r;
	//*/
}


void main()
{
	vec4	pos =		gl_TessCoord.x * gl_in[0].gl_Position + 
						gl_TessCoord.y * gl_in[1].gl_Position +
						gl_TessCoord.z * gl_in[2].gl_Position;
				 
	Output.vTexcoord =	gl_TessCoord.x * Input[0].vTexcoord +
						gl_TessCoord.y * Input[1].vTexcoord +
						gl_TessCoord.z * Input[2].vTexcoord;
	
	pos.y += PCF( Output.vTexcoord ) * unParams.fHeightScale;
	gl_Position = unTransform.MVP * pos;
}


//-----------------------------------------------------------------------------
// [FRAGMENT]

#version 410 core
#pragma optimize(on)

layout(location = 0, index = 0) out vec4	outColor;

uniform sampler2D	unDiffuseMap;
uniform sampler2D	unNormalMap;

layout(std140)
uniform inMaterial {
	vec3	vLightNormal;
	float	fHeightScale;
	float	fDetailLevel;
	float	fMaxLevel;
	float	fQuadSize;
} unParams;


in	TEvalData {
	vec2	vTexcoord;
} Input;


void main()
{
	vec2	norm_tc = vec2( Input.vTexcoord.x, Input.vTexcoord.y );
	vec3	normal1 = normalize( unParams.vLightNormal );
	vec3	normal2 = normalize( texture( unNormalMap, norm_tc ).rgb );
	
	outColor	  = texture( unDiffuseMap, Input.vTexcoord );
	outColor.rgb *= clamp( dot( normal1, normal2 ) * 2.0 - 1.0, 0.0, 1.0 );
}

// [END]
